package com.desay.pangoo.itmt.config;

import java.util.*;
import java.util.stream.Collectors;

import com.desay.pangoo.common.lite.lang.web.BusinessException;
import com.desay.pangoo.common.lite.lang.web.CommonResponse;
import com.desay.pangoo.itmt.enums.ExceptionCodeEnum;
import com.desay.pangoo.itmt.enums.OrgRoleEnum;
import com.desay.pangoo.itmt.enums.ReviewTypeEnum;
import com.desay.pangoo.itmt.feign.UserSystemRequestService;
import com.thoughtworks.xstream.mapper.Mapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.desay.pangoo.itmt.constants.Constant;
import com.desay.pangoo.itmt.constants.TechOnlineReviewFileds;
import com.desay.pangoo.itmt.entity.*;
import com.desay.pangoo.itmt.feign.FeishuRequestService;
import com.desay.pangoo.itmt.repository.*;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HtmlUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 消息推送定时任务
 *
 * @author uidq1163
 */
@Component
@EnableAsync
@Slf4j
public class TechOnlineReviewSchedule {

	/**
	 * ITMT_LEADER
	 */
	public static final String ITMT_LEADER = "ITMT_LEADER";

	/**
	 * ITMT_SUB_LEADER
	 */
	public static final String ITMT_SUB_LEADER = "ITMT_SUB_LEADER";

	public static final String PLITMT_LEADER = "PLITMT_LEADER";
	/** TMT 成员 */
	public static final String ITMT_MEMBER = "ITMT_MEMBER";

	public static final String ITMT_TSP = "ITMT_TSP";
	public static final String ITMT_PRG = "ITMT_PRG";

	private static final String BEARER = "Bearer ";
	/**
	 * null未开启评审，1开始评审，0：关闭评审
	 */
	private static final String FIELD_OPENREVIEW = "openReview";
	private static final String FIELD_REVIEWRESULT = "reviewResult";
	private static final String FIELD_OPENRELEVANT = "openRelevant";
	private static final String FEISHU_CONTENT = "content";
	private static final String FEISHU_USER_ID = "user_id";
	private static final String FEISHU_USER_NAME = "user_name";
	private static final String FEISHU_TITLE = "title";
	private static final String MSG_TITLE = "提案参会人员名单";
	private static final String MSG_TITLE_NAME = "技术提案名称：";
	private static final String MSG_AUDIT_NAME = "旁听人员：";
	private static final String MSG_REVIEW_NAME = "评审人员：";
	private static final String FEISHU_ZH_CN = "zh_cn";
	private static final String FEISHU_RECEIVE_ID = "receive_id";
	private static final String FEISHU_MSG_TYPE = "msg_type";
	private static final String FEISHU_RICH_SUMMARY = "rich_summary";
	private static final String FEISHU_RICH_DESCRIPTION = "rich_description";
	private static final String FEISHU_PLATFORM_I18N_NAME = "platform_i18n_name";
	private static final String FEISHU_ORIGIN = "origin";
	private static final String FEISHU_COLLABORATOR_IDS = "collaborator_ids";

	private static final String FEEDBACK_URL = "/relevantByFeedBackList?progressId=";
	/**
	 * 换行符号
	 */
	private static final String NEWLINE_SYMBOL = "\n";
	/**
	 * 文字前引号（转义符号）
	 */
	private static final String QUOTATION_SYMBOL = "\"";

	@Autowired
	FeishuRequestService feishuRequestService;
	@Autowired
	TechOnlineReviewTMTRepository techOnlineReviewTMTRepository;
	@Autowired
	private MailLogEntityRepository mailLogEntityRepository;
	@Autowired
	private UserSystemRequestService userSystemRequestService;
	@Value("${itmt.host}")
	String host;

	@Value("${itmt.project.url}")
	private String projectPreUrl;

	@Value("${itmt.techNews.url}")
	private String techNewsPreUrl;
	/**
	 * 网关地址
	 */
	@Value("${itmt.zuul.host}")
	String zuulHost;
	/**
	 * 网关授权码
	 */
	@Value("${itmt.zuul.token}")
	String zuulToken;

	/**
	 * 技术提案:相关性审核
	 */
	@Value("${itmt.relevant.url}")
	String relevantUrl;

	@Autowired
	private TechOnlineReviewRepository techOnlineReviewRepository;

	@Autowired
	private TechOnlineReviewRelevantRepository techOnlineReviewRelevantRepository;

	@Autowired
	private OrgChartRepository orgChartRepository;

	private static final String YYYYMMDD = "yyyyMMdd";

	/**
	 * ITMT ChairMan:1，ITMT Leader:2，ITMT SubLeader:3，TMT成员:4，TSP:5，PRG:6
	 *
	 * @param groupName
	 * @return
	 */
	public List<String> getUserGroupLoginInfo(String groupName) {
		List<OrgChartEntity> listObject = null;
		if (groupName.equals(ITMT_LEADER)) {
			listObject = orgChartRepository.findByOrgRole(2);
		} else if (groupName.equals(ITMT_SUB_LEADER)) {
			listObject = orgChartRepository.findByOrgRole(3);
		} else if (groupName.equals(ITMT_MEMBER)) {
			listObject = orgChartRepository.findByOrgRole(4);
		} else if (groupName.equals(ITMT_TSP)) {
			listObject = orgChartRepository.findByOrgRole(5);
		} else if (groupName.equals(ITMT_PRG)) {
			listObject = orgChartRepository.findByOrgRole(6);
		} else if (groupName.equals(PLITMT_LEADER)) {
			listObject = orgChartRepository.findByOrgRole(10);
		}
		// 组织角色:ITMT ChairMan:1，ITMT Leader:2，ITMT SubLeader:3，TMT成员:4，TSP:5
		return listObject == null ? new ArrayList<>()
				: listObject.stream().filter(f -> null != f.getEmail()).map(m -> m.getLogin()).toList();
	}

	/**
	 * ITMT提案相关性反馈
	 *
	 * @param entity
	 */
	public void technicalProposal(TechOnlineReviewEntity entity) {
		String token = getFeiShuToken();
		pushRelevantTaskByFeishu(token, entity);

		// 创建评审会日历信息
		try {
			createCalendars(token, entity);
		} catch (Exception e) {
			log.error("---创建评审会日历信息--{}", e);
		}

	}

	/**
	 * 课题变更，邮件通知TSP人员
	 */
	public void dspProposal(Boolean newFlg, TechProjectInfoEntity entity) {
		String url = host + "/" + projectPreUrl + "?workGroupId=" + entity.getTechClass().getWorkGroup().getId()
				+ "&projectId=" + entity.getId();
		JSONObject jSONObject;
		String techName = entity.getTechName();
		try {
			jSONObject = JSON.parseObject(techName);
			if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
					&& null != jSONObject.getString(Constant.JSON_STR)) {
				techName = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 分类名称、编号、修改人、通过人、修改日期
		String token = getFeiShuToken();
		JSONObject messgae = new JSONObject();
		String title = "技术提案变更提醒";
		if (Boolean.TRUE.equals(newFlg)) {
			title = "新增技术提案提醒";
		}
		title = title + QUOTATION_SYMBOL + techName + QUOTATION_SYMBOL;
		messgae.put(FEISHU_RICH_SUMMARY, "[" + title + "]" + "(" + url + ")");
		StringBuilder sb = new StringBuilder();
		sb.append("技术名称：" + techName + NEWLINE_SYMBOL);
		sb.append("技术编号：" + entity.getTechPtn() + NEWLINE_SYMBOL);
		sb.append("工作组：" + entity.getTechClass().getWorkGroup().getWorkGroupName() + NEWLINE_SYMBOL);
		sb.append("分类：" + entity.getTechClass().getClassificationName() + NEWLINE_SYMBOL);
		sb.append("修改人:" + entity.getUpdator() + NEWLINE_SYMBOL);
		sb.append("修改日期:" + DateUtil.format(new Date(), "yyyy-MM-dd") + NEWLINE_SYMBOL);
		messgae.put(FEISHU_RICH_DESCRIPTION, sb.toString());

		JSONObject origin = new JSONObject();
		origin.put(FEISHU_PLATFORM_I18N_NAME, "{\"zh_cn\": \"ITMT工作台\", \"en_us\": \"ITMT Workspace\"}");
		JSONObject href = new JSONObject();
		// 反馈页面链接
		href.put("url", url);
		href.put(FEISHU_TITLE, title);
		origin.put("href", href);
		messgae.put(FEISHU_ORIGIN, origin);
		// 协同者
		List<String> logins = getUserGroupLoginInfo(ITMT_TSP);
		// 执行者
		messgae.put(FEISHU_COLLABORATOR_IDS, logins);
		try {
			feishuRequestService.pushTask(BEARER + token, messgae);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(messgae));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}

	}

	/**
	 * 变更申请，邮件通知
	 *
	 * @param user
	 * @param entity
	 */
	public void applicationRegardingChanges(String user, TechProjectInfoEntity entity, Long applyId) {
		String title = "技术提案变更申请";
		String url = host + "/projectInfoChangeAppr?workGroupId=" + entity.getTechClass().getWorkGroup().getId()
				+ "&applyId=" + applyId;
		JSONObject jSONObject;
		String techName = entity.getTechName();
		try {
			jSONObject = JSON.parseObject(techName);
			if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
					&& null != jSONObject.getString(Constant.JSON_STR)) {
				techName = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 发消息通知
		JSONObject message = new JSONObject();
		String receiveId = user;
		if (receiveId.contains("(") && receiveId.contains(")")) {
			receiveId = receiveId.substring(receiveId.indexOf("(") + 1, receiveId.indexOf(")"));
		}
		message.put(FEISHU_RECEIVE_ID, receiveId);
		message.put(FEISHU_MSG_TYPE, "post");
		JSONObject zhCn = new JSONObject();
		JSONObject msgObject = new JSONObject();
		zhCn.put(FEISHU_ZH_CN, msgObject);
		msgObject.put(FEISHU_TITLE, title);
		JSONArray contentArray = new JSONArray();
		JSONArray allContentArray = new JSONArray();
		// 第一行
		JSONObject mgs1 = new JSONObject();
		// 技术规划评审
		mgs1.put("tag", "a");
		mgs1.put("href", url);
		mgs1.put("text", "课题技术名：" + QUOTATION_SYMBOL + techName + QUOTATION_SYMBOL);
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		// 第三行
		contentArray = new JSONArray();
		mgs1 = new JSONObject();
		mgs1.put("tag", "text");
		mgs1.put("text", "请及时审核变更申请");
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		msgObject.put(FEISHU_CONTENT, allContentArray);
		message.put(FEISHU_CONTENT, zhCn.toString());
		// 通知提案人评审结果
		try {
			feishuRequestService.pushMessage(BEARER + getFeiShuToken(), message);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 获取飞书认证token
	 *
	 * @return
	 */
	private String getFeiShuToken() {
		String bearerToken = "";
		try {
			JSONObject tokenData = new JSONObject();
			tokenData.put("app_id", "cli_a4bd0102fcf1900b");
			tokenData.put("app_secret", "pKf0q8O7gS8xqG42h0diUbEYmKaVybfQ");
			ResponseEntity<Object> reponse = feishuRequestService.getAccessToken(tokenData);
			if (reponse.getStatusCodeValue() == 200) {
				LinkedHashMap<String, Object> repData = (LinkedHashMap<String, Object>) reponse.getBody();
				if (null != repData && repData.get("code").equals(0)) {
					bearerToken = (String) repData.get("tenant_access_token");
				}
			}
		} catch (Exception e) {
			log.error("{}", e);
			throw new BusinessException(ExceptionCodeEnum.NETWORK_ERROR);
		}
		return bearerToken;
	}

	/**
	 * ITMT提案相关性反馈
	 * <p>
	 * { FEISHU_RICH_SUMMARY: "富文本标题[飞书开放平台](https://open.feishu.cn)<br>
	 * ", FEISHU_RICH_DESCRIPTION: "提案人<at id=user_id>uidq1163</at>\n技术域名称
	 * \n技术提案名称\n技术规划提案说明\n评审会时间", "extra": "dGVzdA==", "due": { "time":
	 * "1623124318", "timezone": "Asia/Shanghai", "is_all_day": false },
	 * FEISHU_ORIGIN: { FEISHU_PLATFORM_I18N_NAME: "{\"zh_cn\": \"ITMT工作台\",
	 * \"en_us\": \"IT Workspace\"}", "href": { "url":
	 * "https://support.feishu.com/internal/foo-bar", FEISHU_TITLE:
	 * "反馈一个问题，需要协助排查" } }, "follower_ids": [ "uidq1163" ],
	 * FEISHU_COLLABORATOR_IDS: [ "uidq1163" ] }
	 *
	 * @param entity
	 */
	private void pushRelevantTaskByFeishu(String token, TechOnlineReviewEntity entity) {
		String creator = entity.getCreator();
		JSONObject message = new JSONObject();
		String url = host + "/" + relevantUrl + "?progressId=" + entity.getId();
		message.put(FEISHU_RICH_SUMMARY, "[" + QUOTATION_SYMBOL + entity.getProposalName() + QUOTATION_SYMBOL
				+ "ITMT提案相关性反馈]" + "(" + url + ")");
		String description = entity.getDescription();
		try {
			JSONObject jSONObject = JSON.parseObject(description);
			if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
					&& null != jSONObject.getString(Constant.JSON_STR)) {
				description = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		StringBuilder sb = new StringBuilder();
		sb.append("提案人：" + creator + NEWLINE_SYMBOL);
		sb.append("技术域名称：" + entity.getWorkGroup().getWorkGroupName() + NEWLINE_SYMBOL);
		sb.append("提案名称：" + entity.getProposalName() + NEWLINE_SYMBOL);
		// 技术点信息（编号/名称等）
		if (CollUtil.isNotEmpty(entity.getTechProjects())) {
			StringBuilder techMsg = new StringBuilder();
			entity.getTechProjects().forEach(p -> {
				String techName = p.getTechName();
				try {
					JSONObject jSONObject = JSON.parseObject(techName);
					if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
							&& null != jSONObject.getString(Constant.JSON_STR)) {
						techName = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				techMsg.append(NEWLINE_SYMBOL + techName + "|" + p.getTechPtn());
			});
			sb.append("技术点信息：" + techMsg.toString() + NEWLINE_SYMBOL);
		}
		sb.append("提案说明：" + description + NEWLINE_SYMBOL);
		sb.append("评审会时间：" + DateUtil.format(entity.getReviewDate(), "yyyy-MM-dd ") + entity.getReviewDateHours()
				+ NEWLINE_SYMBOL);
		// 技术规划评审资料下载链接
		if (CollUtil.isNotEmpty(entity.getFiles())) {
			sb.append("评审资料:\n");
			for (TechOnlineReviewFileEntity file : entity.getFiles()) {
				String fileUrl = zuulHost + "/pangooITMT/onlineReview/file/" + file.getId() + "?key=" + zuulToken;
				sb.append("[" + file.getFileName() + "]" + "(" + fileUrl + ")" + NEWLINE_SYMBOL);
			}
		}
		message.put(FEISHU_RICH_DESCRIPTION, sb.toString());

		JSONObject due = new JSONObject();
		Long dueTime = entity.getTmtReviewDueDate().getTime() / 1000;
		due.put("time", dueTime);
		due.put("timezone", "Asia/Shanghai");
		due.put("is_all_day", true);
		message.put("due", due);
		JSONObject origin = new JSONObject();
		JSONObject platform = new JSONObject();
		platform.put(FEISHU_ZH_CN, "ITMT工作台");
		platform.put("en_us", "ITMT Workspace");
		origin.put(FEISHU_PLATFORM_I18N_NAME, "{\"zh_cn\": \"ITMT工作台\", \"en_us\": \"IT Workspace\"}");
		JSONObject href = new JSONObject();
		// 反馈页面链接
		href.put("url", url);
		String title = getTitle(entity);
		href.put(FEISHU_TITLE, QUOTATION_SYMBOL + entity.getProposalName() + QUOTATION_SYMBOL + title + "相关性反馈");
		origin.put("href", href);
		message.put(FEISHU_ORIGIN, origin);
		// 协同者
		List<String> logins = getUserGroupLoginInfo(ITMT_TSP);
		message.put("follower_ids", logins);
		List<String> leaders = getUserGroupLoginInfo(ITMT_LEADER);
		List<String> subLeaders = getUserGroupLoginInfo(ITMT_SUB_LEADER);
		List<String> itmts = new ArrayList<>();
		leaders.stream().filter(l -> !itmts.contains(l)).forEach(l -> itmts.add(l));
		subLeaders.stream().filter(l -> !itmts.contains(l)).forEach(l -> itmts.add(l));
		// 执行者
		message.put(FEISHU_COLLABORATOR_IDS, itmts);

		try {
			ResponseEntity<Object> response = feishuRequestService.pushTask(BEARER + token, message);
			saveTaskId(token, response, entity, dueTime);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}



	/**
	 * 推送消息给TMT成员
	 *
	 * @param judgesType：1正式参会人员，2旁听人员
	 * @param entity
	 * @param tmts
	 */
	public void pushMessageToTmt(Integer judgesType, TechOnlineReviewEntity entity, List<String> tmts) {
		String token = getFeiShuToken();
		String creator = entity.getCreator();
		JSONObject message = new JSONObject();
		String url = host + "/reviewStar?progressId=" + entity.getId() + "&write=true";
		String title = QUOTATION_SYMBOL + entity.getProposalName() + QUOTATION_SYMBOL + getTitle(entity);
		if (judgesType == 1) {
			message.put(FEISHU_RICH_SUMMARY, "[" + title + "]" + "(" + url + ")");
		} else if (judgesType == 2) {
			message.put(FEISHU_RICH_SUMMARY, "[" + title + "旁听]" + "(" + url + ")");
		}
		StringBuilder sb = new StringBuilder();
		sb.append("提案人：" + creator + NEWLINE_SYMBOL);
		sb.append("技术域名称：" + entity.getWorkGroup().getWorkGroupName() + NEWLINE_SYMBOL);
		sb.append(MSG_TITLE_NAME + entity.getProposalName() + NEWLINE_SYMBOL);
		if (null == entity.getOpenRelevant()) {
			if (entity.getReviewType().equals(ReviewTypeEnum.TECH_BU.getType())) {
				sb.append("反馈期限截止日期：" + DateUtil.format(entity.getDueDate(), "yyyy-MM-dd") + NEWLINE_SYMBOL);
				if (Boolean.FALSE.equals(entity.getIsPlReview())) {
					sb.append("存在TMT Leader成员不同意，请查看详情" + NEWLINE_SYMBOL);
				}
			} else {
				sb.append("是否参会反馈期限：" + DateUtil.format(entity.getTmtReviewDueDate(), "yyyy-MM-dd") + NEWLINE_SYMBOL);
			}
		}
		message.put(FEISHU_RICH_DESCRIPTION, sb.toString());

		JSONObject due = new JSONObject();
		Long dueTime = entity.getDueDate().getTime() / 1000;
		due.put("time", dueTime);
		due.put("timezone", "Asia/Shanghai");
		due.put("is_all_day", true);
		message.put("due", due);
		JSONObject origin = new JSONObject();
		origin.put(FEISHU_PLATFORM_I18N_NAME, "{\"zh_cn\": \"ITMT工作台\", \"en_us\": \"ITMT Workspace\"}");
		JSONObject href = new JSONObject();
		// 反馈页面链接
		href.put("url", url);
		href.put(FEISHU_TITLE, title);
		origin.put("href", href);
		message.put(FEISHU_ORIGIN, origin);
		// 协同者
		if (!entity.getReviewType().equals(ReviewTypeEnum.TECH_BU.getType())) {
			List<String> logins = getUserGroupLoginInfo(ITMT_TSP);
			message.put("follower_ids", logins);
		}
		// 执行者
		message.put(FEISHU_COLLABORATOR_IDS, tmts);
		try {
			ResponseEntity<Object> response = feishuRequestService.pushTask(BEARER + token, message);
			saveTaskId(token, response, entity, dueTime);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 每天凌晨1点执行一次检查:TMT相关性反馈期限
	 *
	 * @throws InterruptedException
	 */
	@Scheduled(cron = "0 0/5 * * * ?")
	public void dueDateOnLineReview() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经过期
		c.add(Restrictions.lt(TechOnlineReviewFileds.TMTREVIEWDUEDATE, DateUtil.beginOfDay(new Date()), true));
		// 已经开启相关性反馈通道
		c.add(Restrictions.eq(TechOnlineReviewFileds.OPENRELEVANT, true, true));
		// 没有反馈结果
		c.add(Restrictions.isNull(TechOnlineReviewFileds.REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		if (CollUtil.isNotEmpty(listExist)) {
			String token = getFeiShuToken();
			// 获取ITMT Leader
			List<OrgChartEntity> listObject = orgChartRepository.findByOrgRole(2);
			if (CollUtil.isEmpty(listObject)) {
				return;
			}
			// 【是否参与评审】与【是否需要旁听】反馈结论均调整为【否】
			for (TechOnlineReviewEntity reviewEntity : listExist) {
				// 【是否参与评审】与【是否需要旁听】反馈结论均调整为【否】
				for (OrgChartEntity orgChartEntity : listObject) {
					TechOnlineReviewRelevantEntity relevant;
					try {
						relevant = techOnlineReviewRelevantRepository
								.findByWorkGroupAndTechOnlineReview(orgChartEntity.getWorkGroup(), reviewEntity);
					} catch (Exception e) {
						log.error("{}", orgChartEntity.getLogin(), reviewEntity.getId());
						continue;
					}
					if (null == relevant) {
						relevant = new TechOnlineReviewRelevantEntity();
						relevant.setTechOnlineReview(reviewEntity);
						relevant.setWorkGroup(orgChartEntity.getWorkGroup());
						relevant.setCreator(orgChartEntity.getLogin());
						relevant.setCreatorName(orgChartEntity.getNickName());
						relevant.setIsRelevant(false);
						relevant.setAuditOrNot(false);
						relevant.setDescription("TMT相关性反馈超期，【是否参与评审】与【是否需要旁听】反馈结论均调整为【否】");
						relevant = techOnlineReviewRelevantRepository.save(relevant);
						// 如果申请时选择的【工作组】在反馈中【超时未反馈】，
						// 则默认这个工作组【参与评审】，评委则为【LEADER本人】
						// CrossBreed这个工作组必须【参与评审】，评委则为【LEADER本人】
						if (orgChartEntity.getWorkGroup().getId().equals(reviewEntity.getWorkGroup().getId())
								|| (null != reviewEntity.getCrossBreedWorkGroup() && orgChartEntity.getWorkGroup()
										.getId().equals(reviewEntity.getCrossBreedWorkGroup().getId()))) {
							relevant.setIsRelevant(true);
							relevant.setAuditOrNot(null);
							relevant.setDescription(null);
							// 评委则为【LEADER本人】
							TechOnlineReviewTMTEntity tmtEntity = new TechOnlineReviewTMTEntity();
							tmtEntity.setCreator(orgChartEntity.getLogin());
							tmtEntity.setTechOnlineRelevantReview(relevant);
							tmtEntity.setTechOnlineReview(reviewEntity);
							tmtEntity.setWorkGroup(orgChartEntity.getWorkGroup());
							tmtEntity.setTmtFullUser(orgChartEntity.getNickName());
							tmtEntity.setTmtUser(orgChartEntity.getLogin());
							tmtEntity.setTmtMail(orgChartEntity.getEmail());
							// 正式参会人员:1，旁听人员:2
							tmtEntity.setJudgesType(1);
							techOnlineReviewTMTRepository.save(tmtEntity);
							relevant.setTmtInfos(new HashSet<>(Arrays.asList(tmtEntity)));
							techOnlineReviewRelevantRepository.save(relevant);
						}
					}
				}
				// 关闭相关性反馈通道
				reviewEntity.setOpenRelevant(false);
				techOnlineReviewRepository.save(reviewEntity);
				List<TechOnlineReviewRelevantEntity> relevantList = techOnlineReviewRelevantRepository
						.findByTechOnlineReview(reviewEntity);
				// 推送消息给提案人，参会人员名单
				pushListOfParticipantsByFeishu(token, MSG_TITLE, reviewEntity, relevantList);

				updateTask(reviewEntity.getTaskId());
			}
		}
	}

	/**
	 * 每天5分钟检查一次:14个技术领域均完成反馈,给提案人发送参会人员名单
	 *
	 * @throws InterruptedException
	 */
	@Scheduled(cron = "0 0/5 * * * ?")
	public void completeCorrelationFeedback() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经开启相关性反馈通道
		c.add(Restrictions.eq(FIELD_OPENRELEVANT, true, true));
		// 没有反馈结果
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		if (CollUtil.isNotEmpty(listExist)) {
			String token = getFeiShuToken();
			// 所有ITMT Leader
			List<OrgChartEntity> listObject = orgChartRepository.findByOrgRole(2);
			if (CollUtil.isNotEmpty(listObject)) {
				// 取出所有域的leader
				List<WorkGroupEntity> leaders = listObject.stream().map(OrgChartEntity::getWorkGroup).toList();
				for (TechOnlineReviewEntity reviewEntity : listExist) {
					List<TechOnlineReviewRelevantEntity> relevantList = techOnlineReviewRelevantRepository
							.findByTechOnlineReview(reviewEntity);
					List<WorkGroupEntity> relevantLeaders = relevantList.stream()
							.map(TechOnlineReviewRelevantEntity::getWorkGroup).toList();
					// 是不是所有域都已经反馈完
					if (relevantLeaders.containsAll(leaders) && relevantLeaders.size() >= leaders.size()) {
						reviewEntity.setOpenRelevant(false);
						techOnlineReviewRepository.save(reviewEntity);
						// 推送消息给提案人，参会人员名单
						pushListOfParticipantsByFeishu(token, MSG_TITLE, reviewEntity, relevantList);

						updateTask(reviewEntity.getTaskId());
					}
				}
			}
		}
	}

	/**
	 * 系统向提案人发送参会人员名单
	 *
	 * @param token
	 * @param title
	 * @param relevantList
	 *            相关性反馈列表
	 */
	public void pushListOfParticipantsByFeishu(String token, String title, TechOnlineReviewEntity reviewEntity,
			List<TechOnlineReviewRelevantEntity> relevantList) {
		if (StringUtils.isEmpty(token)) {
			token = getFeiShuToken();
		}
		JSONObject messgae = new JSONObject();
		String receiveId = reviewEntity.getCreator();
		if (receiveId.contains("(") && receiveId.contains(")")) {
			receiveId = receiveId.substring(receiveId.indexOf("(") + 1, receiveId.indexOf(")"));
		}
		messgae.put(FEISHU_RECEIVE_ID, receiveId);
		messgae.put(FEISHU_MSG_TYPE, "post");
		JSONObject zhCn = new JSONObject();
		JSONObject msgObject = new JSONObject();
		zhCn.put(FEISHU_ZH_CN, msgObject);
		if (null != reviewEntity.getParent()) {
			msgObject.put(FEISHU_TITLE,
					QUOTATION_SYMBOL + reviewEntity.getProposalName() + QUOTATION_SYMBOL + "再次评审" + title);
		} else {
			msgObject.put(FEISHU_TITLE, QUOTATION_SYMBOL + reviewEntity.getProposalName() + QUOTATION_SYMBOL + title);
		}
		JSONArray contentArray = new JSONArray();
		// 第一行
		JSONObject mgs1 = new JSONObject();
		mgs1.put("tag", "a");
		String url = host + FEEDBACK_URL + reviewEntity.getId();
		mgs1.put("href", url);
		title = getTitle(reviewEntity);
		mgs1.put("text", MSG_TITLE_NAME + reviewEntity.getProposalName());
		contentArray.add(mgs1);

		JSONArray allContentArray = new JSONArray();
		allContentArray.add(contentArray);
		// 第二行
		// 参与评审的领域和评委（表格）
		relevantList.stream()
				.filter(r -> Boolean.TRUE.equals(r.getIsRelevant()) && CollUtil.isNotEmpty(r.getTmtInfos()))
				.forEach(r -> {
					JSONArray contentParticipator = new JSONArray();
					JSONObject mgsTitle = new JSONObject();
					mgsTitle.put("tag", "text");
					if (null == r.getWorkGroup()) {
						mgsTitle.put("text", "参与评审域：NA");
					} else {
						mgsTitle.put("text", "参与评审域：" + r.getWorkGroup().getWorkGroupName());
					}
					contentParticipator.add(mgsTitle);
					allContentArray.add(contentParticipator);

					// 评审人员
					List<TechOnlineReviewTMTEntity> participatorList = r.getTmtInfos().stream()
							.filter(t -> null != t.getJudgesType() && t.getJudgesType() == 1).toList();
					if (CollUtil.isNotEmpty(participatorList)) {
						// 换行
						JSONArray participator = new JSONArray();
						mgsTitle = new JSONObject();
						mgsTitle.put("tag", "text");
						mgsTitle.put("text", MSG_REVIEW_NAME);
						participator.add(mgsTitle);
						participatorList.forEach(t -> {
							JSONObject mgsUser = new JSONObject();
							mgsUser.put("tag", "at");
							mgsUser.put(FEISHU_USER_ID, t.getTmtUser());
							mgsUser.put(FEISHU_USER_NAME, t.getTmtFullUser());
							participator.add(mgsUser);
						});
						allContentArray.add(participator);
					}

					// 换行
					// 旁听人员
					List<TechOnlineReviewTMTEntity> auditList = r.getTmtInfos().stream()
							.filter(t -> null != t.getJudgesType() && t.getJudgesType() == 2).toList();
					if (CollUtil.isNotEmpty(auditList)) {
						JSONArray audit = new JSONArray();
						mgsTitle = new JSONObject();
						mgsTitle.put("tag", "text");
						mgsTitle.put("text", MSG_AUDIT_NAME);
						audit.add(mgsTitle);
						auditList.forEach(t -> {
							JSONObject mgsUser = new JSONObject();
							mgsUser.put("tag", "at");
							mgsUser.put(FEISHU_USER_ID, t.getTmtUser());
							mgsUser.put(FEISHU_USER_NAME, t.getTmtFullUser());
							audit.add(mgsUser);
						});
						allContentArray.add(audit);
					}
				});

		// 旁听人员
		relevantList.stream()
				.filter(r -> Boolean.TRUE.equals(r.getAuditOrNot()) && CollUtil.isNotEmpty(r.getTmtInfos()))
				.forEach(r -> {
					JSONArray contentAudit = new JSONArray();
					JSONObject mgsTitle = new JSONObject();
					mgsTitle.put("tag", "text");
					if (null == r.getWorkGroup()) {
						mgsTitle.put("text", "参与旁听域：NA");
					} else {
						mgsTitle.put("text", "参与旁听域：" + r.getWorkGroup().getWorkGroupName());
					}
					contentAudit.add(mgsTitle);
					allContentArray.add(contentAudit);

					JSONArray audit = new JSONArray();
					mgsTitle = new JSONObject();
					mgsTitle.put("tag", "text");
					mgsTitle.put("text", MSG_AUDIT_NAME);
					audit.add(mgsTitle);
					r.getTmtInfos().stream().forEach(t -> {
						JSONObject mgsUser = new JSONObject();
						mgsUser.put("tag", "at");
						mgsUser.put(FEISHU_USER_ID, t.getTmtUser());
						mgsUser.put(FEISHU_USER_NAME, t.getTmtFullUser());
						audit.add(mgsUser);
					});
					allContentArray.add(audit);
				});

		// 第三行
		contentArray = new JSONArray();
		mgs1 = new JSONObject();
		mgs1.put("tag", "text");
		mgs1.put("text", "您向ITMT发起的" + title + "相关性反馈已经完成，请及时向评委及旁听人员发送会议邀请");
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		msgObject.put(FEISHU_CONTENT, allContentArray);
		messgae.put(FEISHU_CONTENT, zhCn.toString());
		try {
			feishuRequestService.pushMessage(BEARER + token, messgae);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(messgae));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 检查评审结果
	 */
	@Scheduled(cron = "0 0/1 * * * ?")
	public void checkOnlineViewClosed() {
		String token = getFeiShuToken();
		closeUnOpenReview(token);
		closeOpenReview(token);
		allPartOpenReview(token);
		// BU 评审结果
		closeBuReview(token);
	}

	/**
	 * 触发条件：流程结束期限，没有点击【评审开始】或无人反馈
	 */
	private void closeUnOpenReview(String token) {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经过期
		c.add(Restrictions.lt("dueDate", DateUtil.beginOfDay(new Date()), true));
		// 还未开始反馈
		c.add(Restrictions.isNull(FIELD_OPENREVIEW));
		c.add(Restrictions.ne(TechOnlineReviewFileds.REVIEWTYPE, ReviewTypeEnum.TECH_BU.getType(), true));
		// 还没有最终评审结果的提案
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		listExist.stream().forEach(t -> {
			// 关闭反馈通道
			t.setOpenReview(false);
			// 设置评审结果为不通过
			t.setReviewResult(false);
			t.setDisruptiveReview(0d);
			t.setIsCrossReview(false);
			techOnlineReviewRepository.save(t);
			// 评审结论：通知提案人
			pushMessageToCreator(token, t);
			// 更新任务为完成
			updateTask(t.getTaskId());
		});
	}

	/**
	 * 触发条件：流程结束期限，已经点击【评审开始】且有评委反馈
	 */
	private void closeOpenReview(String token) {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经过期
		c.add(Restrictions.lt("dueDate", DateUtil.beginOfDay(new Date()), true));
		// null未开启评审，1开始评审，0：关闭评审
		// 评审开始
		c.add(Restrictions.eq(FIELD_OPENREVIEW, true, true));
		// 还没有最终评审结果的提案
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		listExist.stream().forEach(t -> {
			// 关闭反馈通道
			t.setOpenReview(false);
			// 未反馈的评委，实际参会状态均调整为【否】
			List<TechOnlineReviewTMTEntity> list = techOnlineReviewTMTRepository.findByTechOnlineReview(t);
			if (CollUtil.isNotEmpty(list)) {
				list.stream().filter(p -> Boolean.TRUE.equals(p.getIsParticipate()) && null == p.getIsPassed())
						.forEach(tmt -> {
							tmt.setIsParticipate(false);
							tmt.setReviewContent("流程结束：未反馈的评委，实际参会状态均调整为【弃权】");
							techOnlineReviewTMTRepository.save(tmt);
						});
			}
			// 评审规则：一票否决
			// 所有参会人员
			List<TechOnlineReviewTMTEntity> participateList = list.stream()
					.filter(ps -> Boolean.TRUE.equals(ps.getIsParticipate())).toList();
			if (CollUtil.isEmpty(participateList)) {
				// 没有人参与评审：评审不通过
				// 关闭反馈通道
				t.setOpenReview(false);
				t.setReviewResult(false);
				t.setDisruptiveReview(0d);
				t.setIsCrossReview(false);
				techOnlineReviewRepository.save(t);
				pushMessageToCreator(token, t);
				return;
			}
			// 是否有人反馈评审结果
			List<TechOnlineReviewTMTEntity> unpart = participateList.stream().filter(part -> null == part.getIsPassed())
					.toList();
			// 参会人员==未反馈人员：说明没有人反馈，直接设置评审结果为不通过
			if (participateList.size() == unpart.size()) {
				t.setReviewResult(false);
			} else {
				// 评审规则：一票否决
				List<TechOnlineReviewTMTEntity> disPassed = participateList.stream()
						.filter(ps -> Boolean.FALSE.equals(ps.getIsPassed())).toList();
				t.setReviewResult(CollUtil.isEmpty(disPassed));
			}
			// 只有技术评审才会有颠覆性认证和跨越认定
			if (t.getReviewType() == 1) {
				if (Boolean.TRUE.equals(t.getReviewResult())) {
					technologyIdentification(t, participateList);
				} else {
					t.setDisruptiveReview(0d);
					t.setIsCrossReview(false);
				}
			}
			techOnlineReviewRepository.save(t);
			// 发消息通知
			pushMessageToCreator(token, t);
			// 更新任务为完成
			updateTask(t.getTaskId());
			//计算最终领先度和贡献度
			computeFinalLsAndCb(t,list);
		});
	}

	/**
	 * 颠覆性技术认定:平均分超过6分认定为通过<br>
	 * 跨域技术:超过50%（参与投票人员，同意跨域技术占比）为通过
	 *
	 * @param review
	 * @param participateList
	 */
	private void technologyIdentification(TechOnlineReviewEntity review,
			List<TechOnlineReviewTMTEntity> participateList) {
		// 颠覆性技术认定:平均分超过6分认定为通过
		if (Boolean.TRUE.equals(review.getIsDisruptive())) {
			Double avg = participateList.stream().map(p -> {
				Double all = Double.valueOf(p.getMaturity() == null ? 0 : p.getMaturity())
						+ (p.getNeed() == null ? 0 : p.getNeed()) + (null == p.getCostSaving() ? 0 : p.getCostSaving())
						+ (p.getDiffrentiation() == null ? 0 : p.getDiffrentiation());
				return all / 4.0;
			}).toList().stream().collect(Collectors.averagingDouble(Number::doubleValue));
			review.setDisruptiveReview(avg);
		}

		// 跨域技术:超过50%（参与投票人员，同意跨域技术占比）为通过
		if (Boolean.TRUE.equals(review.getIsCross())) {
			Long isPassed = participateList.stream().filter(p -> Boolean.TRUE.equals(p.getIsCross())).count();
			Long disPassed = participateList.stream().filter(p -> Boolean.FALSE.equals(p.getIsCross())).count();
			Float precent = isPassed > 0 ? (Float.valueOf(isPassed) / (isPassed + disPassed)) : 0;
			review.setIsCrossReview(precent >= 0.5);
		}
	}

	/**
	 * 所有参会评委均完成评审提交
	 */
	private void allPartOpenReview(String token) {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// null未开启评审，1开始评审，0：关闭评审
		// 评审开始
		c.add(Restrictions.eq(FIELD_OPENREVIEW, true, true));
		// 还没有最终评审结果的提案
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		listExist.stream().forEach(t -> {
			// 未参会的评委，实际参会状态均调整为【否】
			List<TechOnlineReviewTMTEntity> list = techOnlineReviewTMTRepository.findByTechOnlineReview(t);
			// 评审规则：一票否决
			// 所有参会人员
			List<TechOnlineReviewTMTEntity> participateList = list.stream()
					.filter(ps -> Boolean.TRUE.equals(ps.getIsParticipate())).toList();
			if (CollUtil.isEmpty(participateList)) {
				// 没有人参与评审：评审不通过
				// 关闭反馈通道
				t.setOpenReview(false);
				t.setReviewResult(false);
				t.setDisruptiveReview(0d);
				t.setIsCrossReview(false);
				techOnlineReviewRepository.save(t);
				pushMessageToCreator(token, t);
				return;
			}
			// 是否有人反馈评审结果
			List<TechOnlineReviewTMTEntity> disPart = participateList.stream()
					.filter(part -> null == part.getIsPassed()).toList();
			// 未反馈人员==0：说明全部评审都反馈完成
			if (CollUtil.isEmpty(disPart)) {
				// 关闭反馈通道
				t.setOpenReview(false);
				// 评审规则：一票否决
				List<TechOnlineReviewTMTEntity> disPassed = participateList.stream()
						.filter(ps -> Boolean.FALSE.equals(ps.getIsPassed())).toList();
				t.setReviewResult(CollUtil.isEmpty(disPassed));
				// 评审类型: reviewType :技术规划评审:1，技术定义与研究任务书评审:2，技术成果交付评审:3
				if (t.getReviewType() == 1) {
					if (Boolean.TRUE.equals(t.getReviewResult())) {
						technologyIdentification(t, participateList);
					} else {
						t.setDisruptiveReview(0d);
						t.setIsCrossReview(false);
					}
				}
				techOnlineReviewRepository.save(t);
				pushMessageToCreator(token, t);
				// 更新任务为完成
				updateTask(t.getTaskId());
				//计算最终领先度和贡献度
				computeFinalLsAndCb(t,list);
			}
		});
	}

	/**
	 * 评审结论：通知提案人
	 *
	 * @param token
	 * @param t
	 */
	private void pushMessageToCreator(String token, TechOnlineReviewEntity t) {
		// 发消息通知
		JSONObject message = new JSONObject();
		String receiveId = t.getCreator();
		if (receiveId.contains("(") && receiveId.contains(")")) {
			receiveId = receiveId.substring(receiveId.indexOf("(") + 1, receiveId.indexOf(")"));
		}
		message.put(FEISHU_RECEIVE_ID, receiveId);
		message.put(FEISHU_MSG_TYPE, "post");
		JSONObject zhCn = new JSONObject();
		JSONObject msgObject = new JSONObject();
		zhCn.put(FEISHU_ZH_CN, msgObject);
		String title = getTitle(t);
		msgObject.put(FEISHU_TITLE, title + "结束提醒");
		JSONArray contentArray = new JSONArray();
		JSONArray allContentArray = new JSONArray();
		// 第一行
		JSONObject mgs1 = new JSONObject();
		// 技术规划评审
		String url = host + FEEDBACK_URL + t.getId();
		mgs1.put("tag", "a");
		mgs1.put("href", url);
		mgs1.put("text", "您提交的" + title + QUOTATION_SYMBOL + t.getProposalName() + "\"已经结束");
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		// 第二行
		contentArray = new JSONArray();
		mgs1 = new JSONObject();
		mgs1.put("tag", "text");
		mgs1.put("text", "技术域:" + t.getWorkGroup().getWorkGroupName());
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		// 第三行
		contentArray = new JSONArray();
		mgs1 = new JSONObject();
		mgs1.put("tag", "text");
		mgs1.put("text", "评审结论:" + (Boolean.TRUE.equals(t.getReviewResult()) ? "通过" : "不通过"));
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		msgObject.put(FEISHU_CONTENT, allContentArray);
		message.put(FEISHU_CONTENT, zhCn.toString());
		// 通知提案人评审结果
		try {
			feishuRequestService.pushMessage(BEARER + token, message);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 获取消息title<br>
	 * 评审类型: reviewType :<br>
	 * 技术规划评审:1，<br>
	 * 技术定义与研究任务书评审:2<br>
	 * 技术成果交付评审:3
	 *
	 * @param entity
	 * @return
	 */
	private String getTitle(TechOnlineReviewEntity entity) {
		String title = "";
		if (entity.getReviewType() == 1) {
			title = "技术规划评审";
		} else if (entity.getReviewType() == 2) {
			title = "技术定义与研究任务书评审";
		} else if (entity.getReviewType() == 3) {
			title = "技术交付评审";
		} else if (entity.getReviewType() == 4) {
			title = "BU TMT批准技术课题";
		}
		return title;
	}

	/**
	 * 触发条件：参会反馈期限<br>
	 * 触发条件：全部评委完成反馈
	 *
	 * @throws InterruptedException
	 *             TMTREVIEWDUEDATE字段小于当天开始时间，意味着是否参会反馈期限已过。
	 *             FIELD_OPENRELEVANT字段为null，表示已经开启相关性反馈通道的情况（这里可能逻辑上更准确的表述是判断是否未开启相关性反馈通道，但从代码字面看是判断为null）。
	 *             REVIEWTYPE字段不等于TECH_BU类型对应的枚举值，表示不是某种特定类型的评审。
	 *             FIELD_REVIEWRESULT字段为null，也就是没有反馈结果的情况。
	 */
	@Scheduled(cron = "0 0/5 * * * ?")
	public void secondReviewOnLineReview() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 是否参会反馈期限
		c.add(Restrictions.lt(TechOnlineReviewFileds.TMTREVIEWDUEDATE, DateUtil.beginOfDay(new Date()), true));
		// 相关性反馈通道为空
		c.add(Restrictions.isNull(FIELD_OPENRELEVANT));
		c.add(Restrictions.ne(TechOnlineReviewFileds.REVIEWTYPE, ReviewTypeEnum.TECH_BU.getType(), true));
		// 没有反馈结果
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		if (CollUtil.isNotEmpty(listExist)) {
			String token = getFeiShuToken();
			// 【是否参与评审】与【是否需要旁听】反馈结论均调整为【否】
			for (TechOnlineReviewEntity reviewEntity : listExist) {
				// 关闭相关性反馈通道
				reviewEntity.setOpenRelevant(false);
				techOnlineReviewRepository.save(reviewEntity);
				List<TechOnlineReviewTMTEntity> tmtList = techOnlineReviewTMTRepository
						.findByTechOnlineReviewAndJudgesType(reviewEntity, 1);
				for (TechOnlineReviewTMTEntity t : tmtList) {
					if (null == t.getIsParticipate()) {
						// 反馈结论均调整为【否】
						t.setIsParticipate(false);
						if (Boolean.FALSE.equals(t.getIsPassed())) {
							t.setIsParticipate(true);
						}
					}
					// 重置评审结果状态
					t.setIsPassed(null);
				}

				techOnlineReviewTMTRepository.saveAll(tmtList);
				List<TechOnlineReviewTMTEntity> auditList = techOnlineReviewTMTRepository
						.findByTechOnlineReviewAndJudgesType(reviewEntity, 2);

				// 推送消息给提案人，参会人员名单
				pushListOfParticipantsByFeishuSecond(token, MSG_TITLE, reviewEntity, tmtList, auditList);


			}
		}
	}
	//根据评审反馈计算最终的领先度和贡献度
	public void computeFinalLsAndCb(TechOnlineReviewEntity reviewEntity,List<TechOnlineReviewTMTEntity> tmtList){
		double totalScore = 0;
		Integer finalResult = 0;
		double averageScore = 0;
		// 统计technologyLeadership属性值为1的数量
		long countValue1 = tmtList.stream()
				.filter(entity -> entity.getTechnologyLeadership() == 1)
				.count();

		// 统计technologyLeadership属性值为2的数量
		long countValue2 = tmtList.stream()
				.filter(entity -> entity.getTechnologyLeadership() == 2)
				.count();

		// 统计technologyLeadership属性值为3的数量
		long countValue3 = tmtList.stream()
				.filter(entity -> entity.getTechnologyLeadership() == 3)
				.count();

		// 根据不同值对应的分数计算总分
		totalScore = countValue1 * 1.5 + countValue2 * 1 + countValue3 * 0.7;
		// 计算均值，注意分母可能为0的情况，这里做简单处理，如果列表为空，默认均值为0
		averageScore = tmtList.isEmpty()? 0 : totalScore / tmtList.size();
		// 根据均值确定最终结果
		if(averageScore == 0){
			finalResult = null;
		}
		else if (averageScore >= 0 && averageScore <= 0.7) {
			finalResult = 3;
		} else if (averageScore > 0.7 && averageScore <= 1) {
			finalResult = 2;
		} else {
			finalResult = 1;
		}
		reviewEntity.setFinalTechnologyLeadership(finalResult);
		// 统计technologyContribution属性值为1的数量
		countValue1 = tmtList.stream()
				.filter(entity -> entity.getTechnologyContribution() == 1)
				.count();

		// 统计technologyContribution属性值为2的数量
		countValue2 = tmtList.stream()
				.filter(entity -> entity.getTechnologyContribution() == 2)
				.count();

		// 统计technologyContribution属性值为3的数量
		countValue3 = tmtList.stream()
				.filter(entity -> entity.getTechnologyContribution() == 3)
				.count();

		// 统计technologyContribution属性值为4的数量
		long countValue4 = tmtList.stream()
				.filter(entity -> entity.getTechnologyContribution() == 4)
				.count();

		// 根据不同值对应的分数计算总分
		totalScore = countValue1 * 0.3 + countValue2 * 0.2 + countValue3 * 0.1 + countValue4 * 0.05;
		// 计算均值，如果列表为空，默认均值为0
		averageScore = tmtList.isEmpty()? 0 : totalScore / tmtList.size();

		// 根据均值确定最终结果
		if(averageScore == 0){
			finalResult = null;
		}
		else if (averageScore > 0 && averageScore <= 0.05) {
			finalResult = 4;
		} else if (averageScore > 0.05 && averageScore <= 0.1) {
			finalResult = 3;
		} else if (averageScore > 0.1 && averageScore <= 0.2) {
			finalResult = 2;
		} else {
			finalResult = 1;
		}
		reviewEntity.setFinalTechnologyContribution(finalResult);
		techOnlineReviewRepository.save(reviewEntity);
	}

	/**
	 * 触发条件：参会反馈期限<br>
	 * 触发条件：全部评委完成反馈
	 *
	 * @throws InterruptedException
	 */
	@Scheduled(cron = "0 0/5 * * * ?")
	public void closeSecondReviewOnLineReview() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经开启相关性反馈通道
		c.add(Restrictions.isNull(FIELD_OPENRELEVANT));
		c.add(Restrictions.ne(TechOnlineReviewFileds.REVIEWTYPE, ReviewTypeEnum.TECH_BU.getType(), true));
		// 没有反馈结果
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		if (CollUtil.isNotEmpty(listExist)) {
			String token = getFeiShuToken();
			for (TechOnlineReviewEntity reviewEntity : listExist) {
				List<TechOnlineReviewTMTEntity> tmtList = techOnlineReviewTMTRepository
						.findByTechOnlineReviewAndJudgesType(reviewEntity, 1);
				// 全部评委完成反馈
				Long unParticipate = tmtList.stream().filter(t -> null == t.getIsParticipate()).count();
				if (unParticipate == 0) {
					// 关闭相关性反馈通道
					reviewEntity.setOpenRelevant(false);
					techOnlineReviewRepository.save(reviewEntity);
					// 推送消息给提案人，参会人员名单
					List<TechOnlineReviewTMTEntity> auditList = techOnlineReviewTMTRepository
							.findByTechOnlineReviewAndJudgesType(reviewEntity, 2);
					// 重置评审结果状态
					tmtList.forEach(t -> t.setIsPassed(null));
					techOnlineReviewTMTRepository.saveAll(tmtList);
					pushListOfParticipantsByFeishuSecond(token, MSG_TITLE, reviewEntity, tmtList, auditList);

				}
			}
		}
	}

	/**
	 * 系统向提案人发送参会人员名单
	 *
	 * @param token
	 * @param title
	 * @param reviewEntity
	 * @param tmtList
	 * @param auditList
	 */
	public void pushListOfParticipantsByFeishuSecond(String token, String title, TechOnlineReviewEntity reviewEntity,
			List<TechOnlineReviewTMTEntity> tmtList, List<TechOnlineReviewTMTEntity> auditList) {
		if (StringUtils.isEmpty(token)) {
			token = getFeiShuToken();
		}
		JSONObject message = new JSONObject();
		String receiveId = reviewEntity.getCreator();
		if (receiveId.contains("(") && receiveId.contains(")")) {
			receiveId = receiveId.substring(receiveId.indexOf("(") + 1, receiveId.indexOf(")"));
		}
		message.put(FEISHU_RECEIVE_ID, receiveId);
		message.put(FEISHU_MSG_TYPE, "post");
		JSONObject zhCn = new JSONObject();
		JSONObject msgObject = new JSONObject();
		zhCn.put(FEISHU_ZH_CN, msgObject);
		if (null != reviewEntity.getParent()) {
			msgObject.put(FEISHU_TITLE,
					QUOTATION_SYMBOL + reviewEntity.getProposalName() + QUOTATION_SYMBOL + "再次评审" + title);
		} else {
			msgObject.put(FEISHU_TITLE, QUOTATION_SYMBOL + reviewEntity.getProposalName() + QUOTATION_SYMBOL + title);
		}
		JSONArray contentArray = new JSONArray();
		// 第一行
		JSONObject mgs1 = new JSONObject();
		mgs1.put("tag", "a");
		String url = host + FEEDBACK_URL + reviewEntity.getId();
		mgs1.put("href", url);
		title = getTitle(reviewEntity);
		mgs1.put("text", MSG_TITLE_NAME + reviewEntity.getProposalName());
		contentArray.add(mgs1);

		JSONArray allContentArray = new JSONArray();
		allContentArray.add(contentArray);
		// 第二行
		// 换行
		JSONObject mgsTitle = new JSONObject();
		if (CollUtil.isNotEmpty(tmtList)) {
			JSONArray participator = new JSONArray();
			mgsTitle.put("tag", "text");
			mgsTitle.put("text", MSG_REVIEW_NAME);
			participator.add(mgsTitle);
			tmtList.stream().filter(t -> Boolean.TRUE.equals(t.getIsParticipate())).forEach(t -> {
				JSONObject mgsUser = new JSONObject();
				mgsUser.put("tag", "at");
				mgsUser.put(FEISHU_USER_ID, t.getTmtUser());
				mgsUser.put(FEISHU_USER_NAME, t.getTmtFullUser());
				participator.add(mgsUser);
			});
			allContentArray.add(participator);
		}

		// 旁听人员
		if (CollUtil.isNotEmpty(auditList)) {
			JSONArray audit = new JSONArray();
			mgsTitle = new JSONObject();
			mgsTitle.put("tag", "text");
			mgsTitle.put("text", MSG_AUDIT_NAME);
			audit.add(mgsTitle);
			auditList.stream().forEach(t -> {
				JSONObject mgsUser = new JSONObject();
				mgsUser.put("tag", "at");
				mgsUser.put(FEISHU_USER_ID, t.getTmtUser());
				mgsUser.put(FEISHU_USER_NAME, t.getTmtFullUser());
				audit.add(mgsUser);
			});
			allContentArray.add(audit);
		}

		// 第三行
		contentArray = new JSONArray();
		mgs1 = new JSONObject();
		mgs1.put("tag", "text");
		mgs1.put("text", "您向ITMT发起的" + title + "相关性反馈已经完成，请及时向评委及旁听人员发送会议邀请");
		contentArray.add(mgs1);
		allContentArray.add(contentArray);

		msgObject.put(FEISHU_CONTENT, allContentArray);
		message.put(FEISHU_CONTENT, zhCn.toString());
		try {
			feishuRequestService.pushMessage(BEARER + token, message);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 保存推送任务ID，设置消息提醒
	 *
	 * @param token
	 * @param response
	 * @param reviewEntity
	 * @param dueTime
	 */
	public void saveTaskId(String token, ResponseEntity<Object> response, TechOnlineReviewEntity reviewEntity,
			Long dueTime) {
		if (response.getStatusCode().equals(HttpStatus.OK)) {
			HashMap<String, Object> body = (HashMap<String, Object>) response.getBody();
			if (body.get("code").equals(0)) {
				HashMap<String, HashMap<String, Object>> data = (HashMap<String, HashMap<String, Object>>) body
						.get("data");
				HashMap<String, Object> task = data.get("task");
				String taskId = (String) task.get("id");
				reviewEntity.setTaskId(taskId);
				techOnlineReviewRepository.save(reviewEntity);
				// 任务结束前8小时提醒
				remindersTask(token, taskId, 8 * 60);
			}
		}
	}

	/**
	 * 保存推送任务ID，为后续消息提醒
	 *
	 * @param response
	 * @param reviewEntity
	 */
	public void saveEventId(ResponseEntity<Object> response, TechOnlineReviewEntity reviewEntity) {
		if (response.getStatusCode().equals(HttpStatus.OK)) {
			HashMap<String, Object> body = (HashMap<String, Object>) response.getBody();
			if (body.get("code").equals(0)) {
				HashMap<String, HashMap<String, Object>> data = (HashMap<String, HashMap<String, Object>>) body
						.get("data");
				HashMap<String, Object> task = data.get("event");
				Object eventId = task.get("event_id");
				reviewEntity.setEventId((String) eventId);
				techOnlineReviewRepository.save(reviewEntity);
			}
		}
	}

	/**
	 * 添加任务提醒
	 *
	 * @param token
	 *            认证token
	 * @param taskId
	 *            任务ID
	 * @param minute
	 *            距离结束时间多少分钟
	 */
	private void remindersTask(String token, String taskId, Integer minute) {
		JSONObject body = new JSONObject();
		body.put("relative_fire_minute", minute);
		feishuRequestService.remindersTask(BEARER + token, taskId, body);
	}

	/**
	 * 公共日历
	 */
	private String calendarId = "feishu.cn_lHRPF94cpmhgcVRarO3yQd@group.calendar.feishu.cn";

	/**
	 * TL发起TMT评审流程后，TMT系统根据TL在提案上填写的时间在YesV上创建会议， 并默认添加TL、TMT本域技术Leader，
	 * 并将后续被选定为评委的人员自动添加到会议参会人list中，同时在YesV上进行会议的通知
	 *
	 * @param token
	 * @param reviewEntity
	 */
	public void createCalendars(String token, TechOnlineReviewEntity reviewEntity) {
		if (StringUtils.isEmpty(token)) {
			token = getFeiShuToken();
		}
		JSONObject body = new JSONObject();
		Date reviewDate = reviewEntity.getReviewDate();
		String[] reviewHours = reviewEntity.getReviewDateHours().split("~");
		String day = DateUtil.format(reviewDate, "yyyy-MM-dd");
		// 开始时间
		JSONObject startTime = new JSONObject();
		Date startDate = DateUtil.parse(day + " " + reviewHours[0], "yyyy-MM-dd HH:mm");
		startTime.put("timestamp", startDate.getTime() / 1000);
		body.put("start_time", startTime);
		// 结束时间
		JSONObject endTime = new JSONObject();
		Date endDate = DateUtil.parse(day + " " + reviewHours[1], "yyyy-MM-dd HH:mm");
		endTime.put("timestamp", endDate.getTime() / 1000);
		body.put("end_time", endTime);
		// 是否需要提醒
		body.put("need_notification", true);
		body.put("attendee_ability", "can_modify_event");
		// title
		body.put("summary", "【" + getTitle(reviewEntity) + "】" + reviewEntity.getProposalName());
		ResponseEntity<Object> response = feishuRequestService.createCalendars(BEARER + token, calendarId, body);
		// 保存日历id
		saveEventId(response, reviewEntity);
		// 默认添加TL、TMT本域技术Leader
		List<String> noticeList = new ArrayList<>();
		noticeList.add(reviewEntity.getCreator());
		OrgChartEntity leaderEntity = orgChartRepository.findByWorkGroupAndOrgRole(reviewEntity.getWorkGroup(), 2);
		if (null != leaderEntity) {
			noticeList.add(leaderEntity.getLogin());
		}
		if (null != reviewEntity.getCrossBreedWorkGroup()) {
			leaderEntity = orgChartRepository.findByWorkGroupAndOrgRole(reviewEntity.getCrossBreedWorkGroup(), 2);
			noticeList.add(leaderEntity.getLogin());
		}
		// 更新日历信息
		updateCalendars(reviewEntity.getEventId(), token, noticeList);
	}

	/**
	 * 更新日程参会人员
	 *
	 * @param eventId
	 *            日程id
	 * @param token
	 *            token
	 * @param ids
	 */
	public void updateCalendars(String eventId, String token, List<String> ids) {
		if (CollUtil.isEmpty(ids)) {
			return;
		}
		if (null == token) {
			token = getFeiShuToken();
		}
		JSONObject body = new JSONObject();
		body.put("need_notification", true);
		List<JSONObject> jsonList = new ArrayList<>();
		body.put("attendees", jsonList);
		ids.forEach(uid -> {
			JSONObject info = new JSONObject();
			info.put("type", "user");
			info.put("is_optional", false);
			String userId = uid;
			if (uid.contains("(") && uid.contains(")")) {
				userId = uid.substring(uid.indexOf("(") + 1, uid.indexOf(")"));
			}
			info.put("user_id", userId);
			info.put("operate_id", "uidq1163");
			jsonList.add(info);
		});
		try {
			feishuRequestService.updateCalendars(BEARER + token, calendarId, eventId, body);
		} catch (Exception e) {
			log.error("更新日程参会人员失败---{}----{}", e, body);
		}
	}

	/**
	 * 触发条件：每天下午3点检查，未完成相关性反馈的评审
	 *
	 * @throws InterruptedException
	 */
	@Scheduled(cron = "0 0 15 * * ?")
	public void pushMessageToItmtReview() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经开启相关性反馈通道
		c.add(Restrictions.eq(FIELD_OPENRELEVANT, true, true));
		// 没有反馈结果
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		// 截至日期为当天
		c.add(Restrictions.eq(TechOnlineReviewFileds.TMTREVIEWDUEDATE, DateUtil.beginOfDay(new Date()), true));

		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		if (CollUtil.isNotEmpty(listExist)) {
			String token = getFeiShuToken();
			List<String> logins = getUserGroupLoginInfo(ITMT_LEADER);
			for (TechOnlineReviewEntity reviewEntity : listExist) {
				// 推送消息提醒ITMT
				pushMessageNoticeItmt(token, logins, reviewEntity);
			}
		}
	}

	/**
	 * 技术评审到期提醒
	 * 
	 * @param token
	 * @param logins
	 * @param entity
	 */
	private void pushMessageNoticeItmt(String token, List<String> logins, TechOnlineReviewEntity entity) {
		// 发消息通知
		String techName = entity.getProposalName();
		JSONObject message = new JSONObject();
		String title = "技术相关性评审到期提醒";
		title = title + QUOTATION_SYMBOL + techName + QUOTATION_SYMBOL;
		String url = host + "/" + relevantUrl + "?progressId=" + entity.getId();
		String dueDate = DateUtil.format(entity.getTmtReviewDueDate(), "yyyy-MM-dd");
		message.put(FEISHU_RICH_SUMMARY, "[您还没有对" + QUOTATION_SYMBOL + entity.getProposalName() + QUOTATION_SYMBOL
				+ "提案进行相关性反馈，截止时间为:" + dueDate + "晚上24:00]" + "(" + url + ")");
		StringBuilder sb = new StringBuilder();
		sb.append("工作组：" + entity.getWorkGroup().getWorkGroupName() + NEWLINE_SYMBOL);
		sb.append("提案名称：" + techName + NEWLINE_SYMBOL);
		sb.append("提案人:" + entity.getCreator() + NEWLINE_SYMBOL);
		sb.append("到期日期:" + dueDate + NEWLINE_SYMBOL);
		message.put(FEISHU_RICH_DESCRIPTION, sb.toString());

		JSONObject origin = new JSONObject();
		origin.put(FEISHU_PLATFORM_I18N_NAME, "{\"zh_cn\": \"ITMT工作台\", \"en_us\": \"ITMT Workspace\"}");
		JSONObject href = new JSONObject();
		// 反馈页面链接
		href.put("url", url);
		href.put(FEISHU_TITLE, title);
		origin.put("href", href);
		message.put(FEISHU_ORIGIN, origin);
		// 执行者
		List<TechOnlineReviewRelevantEntity> list = techOnlineReviewRelevantRepository.findByTechOnlineReview(entity);
		List<String> exitItmt = list.stream().map(item -> item.getCreator()).collect(Collectors.toList());
		// 排除已经反馈过ITMT成员
		List<String> listLogin = logins.stream().filter(element -> !exitItmt.contains(element))
				.collect(Collectors.toList());
		message.put(FEISHU_COLLABORATOR_IDS, listLogin);
		JSONObject due = new JSONObject();
		Long dueTime = entity.getTmtReviewDueDate().getTime() / 1000;
		due.put("time", dueTime);
		due.put("timezone", "Asia/Shanghai");
		due.put("is_all_day", true);
		message.put("due", due);
		feishuRequestService.pushTask(BEARER + token, message);
	}

	/**
	 * TMT技术信息反馈提醒：推送消息给用户
	 * 
	 * @param userList
	 * @param id
	 */
	public void pushTechNewToUsers(List<String> userList, Long id, String techTitle) {
		String url = host + "/" + techNewsPreUrl + "?id=" + id;
		String token = getFeiShuToken();
		JSONObject message = new JSONObject();
		String title = "TMT技术信息反馈提醒";
		title = title + QUOTATION_SYMBOL + techTitle + QUOTATION_SYMBOL;
		message.put(FEISHU_RICH_SUMMARY, "[" + title + "]" + "(" + url + ")");

		JSONObject origin = new JSONObject();
		origin.put(FEISHU_PLATFORM_I18N_NAME, "{\"zh_cn\": \"ITMT工作台\", \"en_us\": \"ITMT Workspace\"}");
		JSONObject href = new JSONObject();
		// 反馈页面链接
		href.put("url", url);
		href.put(FEISHU_TITLE, title);
		origin.put("href", href);
		message.put(FEISHU_ORIGIN, origin);
		// 执行者
		message.put(FEISHU_COLLABORATOR_IDS, userList);
		try {
			feishuRequestService.pushTask(BEARER + token, message);
		} catch (Exception e) {
			log.error("{}", e);
			// 记录飞书推送失败日志
			MailLogEntity mailLog = new MailLogEntity();
			mailLog.setDetails(JSON.toJSONString(message));
			mailLog.setTitle(title);
			mailLog.setStatus(false);
			mailLog.setErrors(e.getMessage());
			mailLogEntityRepository.save(mailLog);
		}
	}

	/**
	 * 更新任务状态
	 * 
	 * @param taskId
	 */
	public void updateTask(String taskId) {
		String token = getFeiShuToken();
		JSONObject body = new JSONObject();
		JSONObject data = new JSONObject();
		body.put("body", data.put("completed_at", System.currentTimeMillis()));
		body.put("update_fields", Arrays.asList("completed_at"));
		try {
			feishuRequestService.updateTask(BEARER + token, taskId, body);
		} catch (Exception e) {
			log.error("{}", e);
		}
	}

	/**
	 * BU 评审到期，关闭评审
	 * 
	 * @param token
	 */
	private void closeBuReview(String token) {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 已经过期
		c.add(Restrictions.lt(TechOnlineReviewFileds.DUEDATE, DateUtil.beginOfDay(new Date()), true));
		// 还没有最终评审结果的提案
		c.add(Restrictions.isNull(FIELD_REVIEWRESULT));
		// BU 评审``
		c.add(Restrictions.isNotNull("isPlReview"));
		//(TechOnlineReviewFileds.ISTYPE4COMMIT, Boolean.TRUE, true))
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		listExist.stream().forEach(reviewEntity -> {
			// 取出PLTMT Leaders
			List<TechOnlineReviewTMTEntity> listPltmts = techOnlineReviewTMTRepository
					.findByTechOnlineReviewAndIsPL(reviewEntity, 1);
			List<TechOnlineReviewTMTEntity> listTMTs = techOnlineReviewTMTRepository
					.findByTechOnlineReviewAndIsPL(reviewEntity, 0);
			// PLTMT Leader的到期反馈检测
			if (Boolean.TRUE.equals(reviewEntity.getIsPlReview())) {
				// 一票否决权
				long countPLTMT = listPltmts.stream().filter(item -> !Boolean.TRUE.equals(item.getIsPassed()))
						.count();
				if (countPLTMT == 0) {
					//关闭pl评审
					reviewEntity.setIsPlReview(false);
					// 重置全部反馈完成截止日期
					ResponseEntity<CommonResponse<Object>> response = userSystemRequestService
							.getWorkDayDiff(DateUtil.format(new Date(), YYYYMMDD), 7);
					String reviewDate = "";
					if (response.getStatusCodeValue() == HttpStatus.OK.value() && Objects.nonNull(response.getBody())) {
						reviewDate = (String) response.getBody().getData();
					}
					reviewEntity.setDueDate(DateUtil.parse(reviewDate, YYYYMMDD));
					// 给TMTLeader发飞书
					List<String> tmts = listTMTs.stream().map(TechOnlineReviewTMTEntity::getTmtUser).toList();
					if (CollUtil.isNotEmpty(tmts)) {
						pushMessageToTmt(1, reviewEntity, tmts);
					}
					// 一票否决，提案失败
				} else {
					reviewEntity.setReviewResult(false);
					techOnlineReviewRepository.save(reviewEntity);
					pushMessageToCreator(token, reviewEntity);
				}
				// PLTMTleader已经提交评审，TMT Leader的到期反馈检测
			} else  {
				// 统计值为true的数量
				long countTrue = listTMTs.stream().filter(item -> Boolean.TRUE.equals(item.getIsPassed())).count();

				// 统计值为false的数量
				long countFalse = listTMTs.stream().filter(item -> Boolean.FALSE.equals(item.getIsPassed())).count();

				// 统计值为null的数量
				long countNull = listTMTs.stream().filter(item -> item.getIsPassed() == null).count();
				// 全部同意提案结束并且参与率达到70%
				if (countFalse == 0 && ((double) countNull / (countNull + countTrue) < 0.3)) {
					reviewEntity.setReviewResult(true);
					pushMessageToCreator(token, reviewEntity);
				} else {
					// 重置截至时间Z
					ResponseEntity<CommonResponse<Object>> response = userSystemRequestService
							.getWorkDayDiff(DateUtil.format(new Date(), YYYYMMDD), 5);
					String reviewDate = "";
					if (response.getStatusCodeValue() == HttpStatus.OK.value() && Objects.nonNull(response.getBody())) {
						reviewDate = (String) response.getBody().getData();
					}
					reviewEntity.setDueDate(DateUtil.parse(reviewDate, YYYYMMDD));
					// 开启PLTMT Leader到期检测
					reviewEntity.setIsPlReview(Boolean.TRUE);
					// 给PLTMTleader发送飞书
					List<String> pltmts = listPltmts.stream().map(TechOnlineReviewTMTEntity::getTmtUser).toList();
					pushMessageToTmt(1, reviewEntity, pltmts);
				}
			}
			techOnlineReviewRepository.save(reviewEntity);
		});
	}
}
